home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
os2
/
dcd.zip
/
dcd
/
dcd.cmd
next >
Wrap
OS/2 REXX Batch file
|
1997-08-11
|
33KB
|
736 lines
/*
@ECHO OFF
ECHO DCD Error: OS/2 Procedures Language 2/REXX not installed.
pause
exit
==============================================================================
DCD - Disk Change Directory
For usage type 'DCD', 'DCD -?', 'DCD -help', or read DCD.DOC.
Roger de Reus (reus@mic.dtu.dk)
==============================================================================
*/
DCD.Version=,
'DCD disk change directory -- v2.00 -- Copyright (c)1995-1997 Roger de Reus '
/* -------------- Options/commands to be executed at startup: ------------- */
/* DCD.Startup="-local -select -partialmatch -uppercase --" is default */
DCD.Startup=""
/* ------------------------------------------------------------------------ */
/* --------------------- Initialize some variables ------------------------ */
DCD.Global=0 /* local drive (0=local,1=global) */
DCD.Next=0 /* user selects possibilities (0=select,1=next) */
DCD.FullMatch=0 /* partial match (0=partial match,1=fullmatch) */
DCD.Case=0 /* not case sensitive (0=not sensitive, 1=sensitive) */
DCD.Exp=0 /* expression mode (0=off, 1=on) */
DCD.Rescan=0 /* rescan (0=no, 1=yes) */
DCD.Separator='-' /* no conversion ('/'=\ to /, '\'= / to \, '-'=as is) */
DCD.Grep=1 /* use grep for wildcard expressions (0=no, 1=yes) */
DCD.RegEx=0 /* use <dir> as regular expression for grep (0=no, 1=yes) */
DCD.GrepOpt='' /* Options passed to grep */
call DCD_Color /* initialize DCD.Color* variables */
DCD.Env='OS2ENVIRONMENT' /* May be useful later... */
DCD.Trc='Off' /* No error tracing per default */
/* ------------------------------------------------------------------------ */
If RxFuncQuery('SysLoadFuncs') then
Do
call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
call SysLoadFuncs
End
signal on halt name DCD_Halt
parse arg DCD.CmdLin
if DCD.CmdLin=''; then call DCD_Exit 1 /* Missing input */
/* Test configuration (DCD environment variable and DCD.Startup string) */
call WhoAmI /* get source DCD.Src.Drv, Path, Name, and Ext */
DCD.CmdLin=value(DCD.Src.Name,,DCD.Env)' 'DCD.CmdLin
DCD.CmdLin=DCD.Startup' 'DCD.CmdLin
DCD.CmdLin=strip(DCD.CmdLin,'L')
DCD.List=DCD.Src.Drv||DCD.Src.Path||DCD.Src.Name'.LST'
DCD.DriveMap=SysDriveMap() /* All drives available */
DCD.Match='' /* No match to start with */
/* Do some stuff */
if DCD.CmdLin=''; then call DCD_Exit 1 /* missing input, suggest -? */
do forever
If (substr(DCD.CmdLin,1,1)='-'|substr(DCD.CmdLin,1,1)='/')&\DCD.Exp; Then Do
Call DCD_Option
Trace Value DCD.Trc /* sorry, this needs to be in main routine... */
End
Else Do /* try to find and change dir */
DCD.Dir=DCD_GetArg('Change to directory: ')
if DCD.CmdLin<>''; then do /* all input is wanted dir */
DCD.Dir=DCD.Dir' 'DCD.CmdLin; DCD.CMdLin=''; end
DCD.CurDir=directory() /* current dir */
if \DCD.Case; then DCD.CurDir=DCD_UpCase(DCD.CurDir)
DCD.CurDrv=filespec('D',DCD.CurDir) /* current drive */
if \DCD.RegEx; then Do /* no fiddling when -regex active! */
if \DCD.Case; then DCD.Dir=DCD_UpCase(DCD.Dir)
call DCD_Separator /* convert \, /, etc. */
DCD.Drv=filespec('D',DCD.Dir) /* wanted drive */
if DCD.Drv<>''; then DCD.Global=0 /* drive spec, override Global */
else; if \DCD.Global; then DCD.Drv=DCD.CurDrv /* local drive */
if \DCD.Global&\Valid_Drive(DCD.Drv); then call DCD_Exit 4 DCD.Drv
DCD.Dir=filespec('P',DCD.Dir)||filespec('N',DCD.Dir) /* path+name */
DCD.Drv.Dir=DCD.Drv||DCD.Dir /* drive, path and name */
End
DCD.FullDir='' /* initialize full dir for changedir */
call Test_Dots /* check if DCD.Dir is of .\.. form */
if DCD.FullDir<>''; then call Change_Dir(DCD.FullDir)
/* time to make a match with the list file... */
call DCD_List('EXIST') /* Check existence of directory listing */
if Verify(DCD.Dir,'*?',M)<>0|DCD.RegEx; then
call DCD_Wild /* Wildcard handling */
else
call DCD_Match
if DCD.FullDir<>''; then
call Change_Dir(DCD.FullDir)
else do
say "I wouldn't expect you to end here... I'll try "DCD.Drv.Dir
call Change_Dir(DCD.Drv.Dir)
end
end
end
return
/* ===========================================================================
DCD_Option: procedure to check command line options.
Usage: call DCD_Option
Input: DCD.CmdLin
Output: DCD.CmdLin (without first argument)
=========================================================================== */
DCD_Option: procedure expose DCD.
parse var DCD.CmdLin Opt DCD.CmdLin
Opt = translate(substr(Opt,2)) /* throw away first character */
select
when abbrev('?',Opt,1); then call DCD_Help
when abbrev('HELP',Opt,1); then call DCD_Help VERBOSE
when abbrev('GLOBAL',Opt,1); then DCD.Global=1
when abbrev('LOCAL',Opt,1); then DCD.Global=0
when abbrev('NEXT',Opt,1); then DCD.Next=1
when abbrev('RR',Opt,2); then DCD.Next=1
when abbrev('ROUNDROBIN',Opt,2); then DCD.Next=1
when abbrev('SELECT',Opt,2); then DCD.Next=0
when abbrev('SCAN',Opt,1); then call DCD_Scan
when abbrev('RESCAN',Opt,2); then Do; DCD.Rescan=1; call DCD_Scan; End
when abbrev('LISTFILE',Opt,2)|abbrev('LST',Opt,3);
then DCD.List=DCD_GetArg('Alternate directory list: ')
when abbrev('FULLMATCH',Opt,1); then DCD.FullMatch=1
when abbrev('PARTIALMATCH',Opt,1);then DCD.FullMatch=0
when abbrev('UPPERCASE',Opt,2); then DCD.Case=0
when abbrev('LOWERCASE',Opt,3); then DCD.Case=1
when abbrev('PUSHDIR',Opt,2); then call DCD_PushDir
when abbrev('POPDIR',Opt,2); then call DCD_PopDir
when abbrev('COLOR',Opt,5); then call DCD_Color ON
when abbrev('EXPRESSION',Opt,1); then DCD.Exp=1
when abbrev('NOGREP',Opt,6); then DCD.Grep=0
when abbrev('REGEX',Opt,5); then DCD.RegEx=1
when abbrev('GREPOPT',Opt,5); then
DCD.GrepOpt=DCD.GrepOpt' 'DCD_GetArg('Option(s) for grep: ')
when abbrev('VERSION',Opt,1); then call DCD_Version
when abbrev('$TRACE',Opt,6); then DCD.Trc=DCD_GetArg('Trace level: ')
when datatype(Opt,'W') & Opt>0; then call DCD_UpTree Opt
when Opt='\'|Opt='/'|Opt='-'; then DCD.Separator=Opt
otherwise; call DCD_Exit 2 '-'Opt
end
return
/* ===========================================================================
DCD_Version: display version number and bag out
=========================================================================== */
DCD_Version: procedure expose DCD.
call charout , DCD.ColorNormal||DCD.Version
call DCD_Exit 0
return
/* ===========================================================================
WhoAmI: determine source, DCD.Src.Drv, Src.Path, Src.Name, Src.Ext
=========================================================================== */
WhoAmI: procedure expose DCD.
parse upper source . . DCD.Src
DCD.Src.Drv=filespec('D',DCD.Src) /* drive */
DCD.Src.Path=filespec('P',DCD.Src) /* path */
DCD.Src.Name=filespec('N',DCD.Src) /* name.ext */
DCD.Src.Ext=right(DCD.Src.Name,lastpos('.',DCD.Src.Name)) /* ext */
DCD.Src.Name=left(DCD.Src.Name,lastpos('.',DCD.Src.Name)-1) /* name */
return
/* ===========================================================================
DCD_UpTree: go `up' in the directory tree
Usage: call DCD_UpTree <n>
=========================================================================== */
DCD_UpTree: procedure expose DCD.
parse arg Count
do I=1 to Count; if directory('..')=''; then Leave; end
call DCD_Exit 0
return
/* ===========================================================================
DCD_PushDir: push current dir in environment variable (DCD_Push)
Usage: call DCD_PushDir
Input: none
Output: none
=========================================================================== */
DCD_PushDir: procedure expose DCD.
PushDir=value(DCD.Src.Name'_Push',directory(),DCD.Env)
return
/* ===========================================================================
DCD_PopDir: jump back to directory set by environment variable.
Usage: call DCD_PopDir
Input: environment variable DCD_Push
Output: error if DCD_Push not set, else call Change_Dir
=========================================================================== */
DCD_PopDir: procedure expose DCD.
PopDir=value(DCD.Src.Name'_Push',,DCD.Env)
if PopDir='' then call DCD_Exit 18
call Change_Dir(PopDir)
return
/* ===========================================================================
DCD_Separator: convert directory separators
=========================================================================== */
DCD_Separator: procedure expose DCD.
select
when DCD.Separator='/'; then DCD.Dir=translate(DCD.Dir,'/','\')
when DCD.Separator='\'; then DCD.Dir=translate(DCD.Dir,'\','/')
when DCD.Separator='-'; then nop;
otherwise; call DCD_Exit 14 DCD.Separator
end
return
/* ===========================================================================
DCD_UpCase: convert some variables to uppercase
attempt foreign language characters as well (code page 850)
Uppercase equivalent of characters after A-Z:
`A 'A ^A "A CC `E 'E ^E "E `I 'I ^I "I ~N `O 'O "O ^O "O ~O `U 'U
^U 'Y AE \O AA ETH THORN
=========================================================================== */
DCD_UpCase: procedure
parse arg Up
UpChr='ABCDEFGHIJKLMNOPQRSTUVWXYZ╖╡╢ÄÇ╘É╥╙▐╓╫╪ÑπαΓÖσδΘΩÜφÆ¥Å╤Φ'
LoChr='abcdefghijklmnopqrstuvwxyzàáâäçèéêëìíîïñòóôöΣùúûü∞æ¢å╨τ'
return translate(Up,UpChr,LoChr)
/* ===========================================================================
Test_Dots: procedure to test if directory consists of dots and (back)slashes
Usage: call Test_Dots
Input: DCD.Dir path and name of directory
DCD.Drv.Dir drive, path and name of directory
Output: DCD.FullDir will bet set to DCD.Drv.Dir on success
=========================================================================== */
Test_Dots: procedure expose DCD.
do I = 1 to length(DCD.Dir)
if verify(substr(DCD.Dir,I,1),'.\/')<>0 then return /* exit if not '.\/' */
end I
select /* test a few invalid combinations */
when pos('...', DCD.Dir)<>0; then call DCD_Exit 9 DCD.Dir
when pos('....',DCD.Dir)<>0; then call DCD_Exit 9 DCD.Dir
when pos('\\', DCD.Dir)<>0; then call DCD_Exit 9 DCD.Dir
when pos('//', DCD.Dir)<>0; then call DCD_Exit 9 DCD.Dir
when pos('/\', DCD.Dir)<>0; then call DCD_Exit 9 DCD.Dir
when pos('\/', DCD.Dir)<>0; then call DCD_Exit 9 DCD.Dir
otherwise DCD.FullDir=DCD.Drv.Dir
end
return
/* ===========================================================================
DCD_Match: procedure to test DCD.Drv and DCD.Dir against directories
in DCD.List file.
Usage: call DCD_Match
Input: DCD.Drv, DCD.Dir
DCD.List: file with directory list
DCD.Global, DCD.Next, DCD.FullMatch: logical variables.
Output: DCD.FullDir: full directory name desired or empty string
DCD.Match: directory name for (last) full match.
Note: output is in fact generated by calling DCD_SelDir.
=========================================================================== */
DCD_Match: procedure expose DCD.
if SysFileSearch(DCD.Dir, DCD.List, Match1)<>0; then call DCD_Exit 10 RC
J=0 /* match counter */
do I = 1 to Match1.0
Tmp=Match1.I; if \DCD.Case then Tmp=DCD_Upcase(Tmp)
if \DCD.Global; then /* drive must match: */
if DCD.Drv <> filespec('D',Tmp); then iterate
/* Make sure match occurs without trailing '\' (indicating subdirs) */
if lastpos(DCD.Dir,Tmp)+length(DCD.Dir)<=lastpos('\',Tmp);
then iterate
if filespec('N',DCD.Dir)<>filespec('N',Tmp); then /* no full match */
do; if DCD.FullMatch; then iterate; end
else /* full match */
if \DCD.FullMatch; then DCD.Match=Match1.I /* set best match */
J=J+1; Match2.J=Match1.I /* something must match if we get here */
end I
Match2.0=J
call DCD_SelDir
return
/* ===========================================================================
DCD_Wild: wildcard matching of directory names
Usage: call DCD_wild
Input: DCD.Drv.Dir DCD.Drv DCD.Dir (DCD.CurDrv)
DCD.Grep - use grep for wildcard matching
DCD.RegEx - 0: cmd.exe wildcard emulation (of * and ?)
1: pass DCD.Drv.Dir to grep as regular expression
Output: DCD.Fulldir (by calling DCD_SelDir which uses stem Match2)
This is a bit of a clutch, rescanning the drive without supporting the
-global option.
This because SysFileTree supports wildcard searching, SysFileSearch doesn't,
and I don't want to write my own code for wildcard matching...
However, this is not how I want it: only the name part of the dir will be
matched. E.g. 'dcd f*' would match foobar, 'dcd f*r' will not match, whereas
I would like it to match both foobar and foo\bar :-(
=========================================================================== */
DCD_Wild: procedure expose DCD.
If DCD.FullMatch Then Do; /* full match with wildcards impossible */
Call DCD_Warn 2 DCD.Drv.Dir; DCD.FullMatch=0; End
/* 4 possibilities:
- RegEx=1, Grep=1: grep noconversion
- RegEx=1, Grep=0: bag out
- RegEx=0, Grep=1: grep converted string
- RegEx=0, Grep=0: no grep
*/
If \DCD.Grep; Then Do /* scan single DCD.Drv */
If DCD.RegEx; Then call DCD_Exit 17 /* Options contradict */
If DCD.Global Then Do /* no global, stay on current drive */
Call DCD_Warn 1 DCD.Drv.Dir; DCD.Drv=DCD.CurDrv; End
if DCD.Case then call DCD_Warn 3 DCD.Drv'\'DCD.Dir
If SysFileTree(DCD.Drv'\'DCD.Dir, Match2, 'SDO')<> 0; Then Do
Say; Call DCD_Exit 5 Drive; End
End
Else Do
Grep = SysSearchPath('PATH','GREP.EXE')
If Grep=''; Then call DCD_Exit 16 /* grep.exe not found on the path */
If \DCD.Case; Then DCD.GrepOpt='-i 'DCD.GrepOpt
'@echo off'
If DCD.RegEx Then
Do /* nothing fancy, ignore all settings */
GrepDir = DCD.Dir; DCD.Drv.Dir = DCD.Dir
End
Else
GrepDir = CvtOS2toGNU(DCD.Drv.Dir)
Grep DCD.GrepOpt GrepDir DCD.List '| RxQueue' /* output to queue */
Match2.0 = Queued()
Do I=1 to Match2.0
Parse Pull Match2.I
End
End
call DCD_SelDir
return
/* ===========================================================================
DCD_SelDir: let user select a directory
Usage: call DCD_SelDir
Input: Match2 - stem containing directories
Output: DCD.FullDir - full directory name on success, otherwise exit
=========================================================================== */
DCD_SelDir: procedure expose DCD. Match2.
if Match2.0=0 then; do
/* no match, last resort: try to switch anyway ... */
if directory(DCD.Drv.Dir)<>''; then exit
if \DCD.FullMatch; then call DCD_Exit 11 DCD.Drv.Dir /* no match */
else call DCD_Exit 12 DCD.Drv.Dir
end
if Match2.0=1 then; do; DCD.FullDir=Match2.1; return; end /* single hit */
/* more hits if we get here */
if \DCD.Next; then do; /* user selects */
parse value SysTextScreenSize() with ScrnRows . /* screen size */
if Match2.0>ScrnRows-1; then
say "Read quickly: more choices than I can show!"
if Match2.0>36; then
say "More choices than I can handle! Use -n option or specify better."
Match2.0=min(36,ScrnRows-1,Match2.0)
NumAlph='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' /* 36 choices */
do I = 1 to Match2.0 /* show choices */
say DCD.ColorPrompt||substr(NumAlph,I,1),
DCD.ColorNormal||Match2.I;
end I
call charout , DCD.ColorPrompt
if DCD.Match=''; then /* prompt */
call charout , "Hit choice or Esc: "DCD.ColorInput
else
call charout , "Hit choice, Esc, or Enter|Space for "DCD.Match":",
DCD.ColorInput
Key=translate(SysGetKey()) /* get reply */
if Key='1B'x; then; call DCD_Exit 0 /* 1B=Escape */
if (Key='0D'x|Key='20'x) & DCD.Match<>''; then do /* 0D=Enter, 20=Space */
DCD.FullDir=DCD.Match; return; end
/* if we get here, real selection was made */
Choice=pos(Key,NumAlph) /* check if valid */
if Choice>0 & Choice<=Match2.0; then DCD.FullDir=Match2.Choice
else do; say ''; call DCD_Exit 13 Key; end /* any other key is invalid */
end /* do user selects */
else do /* round robin mode */
Choice=1 /* default first entry in match list */
do I = 1 to Match2.0 /* check if current dir is in match list */
if DCD.CurDir=Match2.I; then do /* if so, */
if I=Match2.0 then Choice=1; else Choice=I+1 /* pick next in list */
leave /* and leave loop to set DCD.FullDir */
end
end I
DCD.FullDir=Match2.Choice
end
return
/* ===========================================================================
CvtOS2toGNU: try to mimic OS/2 wildcards (? and *) for GNU regular expressions
Usage: GNUregex = CvtOS2toGNU(OS2regex)
=========================================================================== */
CvtOS2toGNU: Procedure
Parse Arg OS2
/* Say "GREP string to be converted: "OS2 */
GNU=''
Do I=1 to Length(OS2)
C=SubStr(OS2,I,1)
Select
When Verify(C,'.\')=0; Then GNU=GNU'\'C
When C='?'; Then GNU=GNU'.'
When C='*'; Then GNU=GNU'.*'
When C=' '; Then GNU=GNU'[[:space:]]'
When C=':'; Then GNU=GNU':.*'
Otherwise; GNU=GNU||C
End
End
If Right(GNU,1)<>'*'; Then
GNU=GNU'$'
Return GNU
/* ===========================================================================
Change_Dir: try to change directory and then exit (with or without error msg).
Usage: call Change_Dir(directory)
=========================================================================== */
Change_Dir: procedure expose DCD.
parse arg Dir
if directory(Dir)='' then call DCD_Exit 8 Dir /* error */
call DCD_Exit 0 /* success */
return
/* ===========================================================================
DCD_List: function to test or delete DCD.List file
Usage: call DCD_List('MODE');
Input: MODE = EXIST: check if DCD.List exists
MODE = DELETE: delete DCD.List
Action: bag out if anything goes wrong
=========================================================================== */
DCD_List: procedure expose DCD.
parse upper arg MODE
if stream(DCD.List,'c','query exists')=''; then do /* file does not exist */
if MODE='EXIST'; then call DCD_Exit 3 DCD.List; end
else do
if MODE='DELETE'; then
if sysfiledelete(DCD.List)<>0; then call DCD_Exit 6 DCD.List; end
return
/* ===========================================================================
DCD_GetArg: return next argument from command line, prompt if necessary
Usage: Var=DCD_GetArg(Prompt);
Input: Prompt - display text if no CmdLin stack empty
DCD.CmdLin - CmdLin stack
Output: Var - First command from CmdLin stack
DCD.CmdLin - CmdLin stack without first argument
=========================================================================== */
DCD_GetArg: procedure expose DCD.
parse var DCD.CmdLin Var DCD.CmdLin
if Var=''; then do;
parse arg Prompt
call charout , DCD.ColorPrompt||Prompt||DCD.ColorInput;
pull DCD.CmdLin; parse var DCD.CmdLin Var DCD.CmdLin;
if Var=''; then call DCD_Exit 15; /* persistently no input, quit */
end
return Var
/* ===========================================================================
DCD_Scan: procedure to scan drives for directories and save to file
Usage: call DCD_Scan
Input: DCD.CmdLin: string with drives
Output: DCD.List file containing directory structure
=========================================================================== */
DCD_Scan: procedure expose DCD.
Drives=DCD_Getarg('Drives to scan: ')
if \DCD.Case; then Drives=DCD_UpCase(Drives)
/* first check if drives are allowed */
Drives.ToDo=''
do I = 1 to length(Drives)
Drive=substr(Drives,I,1)
if verify(Drive,'ABCDEFGHIJKLMNOPQRSTUVWXYZ')=0; then do /* test [A-Z] */
Drive=Drive':'
if \Valid_Drive(Drive); then call DCD_Exit 4 Drive
if Pos(Drive,Drives.ToDo)=0; then Drives.ToDo=Drives.ToDo||Drive' '
/* eliminate double occurences of Drive */
end
end I
If DCD.Rescan then
Do
/* Read in the old list and close it */
Do i=1 while Lines(DCD.List)
OldList.i=LineIn(DCD.List)
End
Call LineOut DCD.List
OldList.0=i-1
End
Else
OldList.0=0
/* bubble sort of drives here, double occurences already eliminated */
Do i=1 to Words(Drives.ToDo)-1
Do j=i+1 to Words(Drives.ToDo)
D1=Word(Drives.ToDo,i)
D2=Word(Drives.ToDo,j)
If D1>D2 then
Do /* only possible because words have same length */
Drives.Todo=Overlay(D2,Drives.ToDo,WordIndex(Drives.ToDo,i))
Drives.Todo=Overlay(D1,Drives.ToDo,WordIndex(Drives.ToDo,j))
End
End j
End i
/* then do the scanning */
N_Drives = 0
M_Ix = 1 /* Merge index */
call charout , DCD.ColorNormal
If DCD.Rescan then
call charout , "Refreshing drive"
Else
call charout , "Scanning drive"
do I = 1 to Words(Drives.ToDo)
Drive=Word(Drives.ToDo,I)
call charout , ' '||Drive
N_Drives = N_Drives+1
if sysfiletree(Drive"\", DirList.N_Drives, 'SDO')<> 0; then do
say; call DCD_Exit 5 Drive
end
end I
/* finally write directory list to file */
call DCD_List('DELETE') /* find DCDLST file; delete if necessary */
If DCD.Rescan then
call charout , " ... updating "DCD.List" ... "
Else
call charout , " ... writing "DCD.List" ... "
do I = 1 to N_Drives
Matched=0
If DCD.Rescan then
/* Merge in prior information on unscanned drives */
Do M_Ix=M_Ix to OldList.0 Until Matched
Select
When Left(OldList.M_Ix,1)<Left(Word(Drives.ToDo,I),1) then
/* Write this record */
if lineout(DCD.List, OldList.M_Ix)<>0;
then call DCD_Exit(7,'DCD.List')
When Left(OldList.M_Ix,1)=Left(Word(Drives.ToDo,I),1) then
/* Bypass this record, alphabetical order assumed */
NOP
Otherwise
/* It's greater, so we have an insertion point */
Matched=1
End /* Select */
End /* Do */
do J = 1 to DirList.I.0
if lineout(DCD.List, DirList.I.J)<>0; then call DCD_Exit(7,'DCD.List')
end J
end I
If DCD.Rescan then
Do M_Ix=M_Ix to OldList.0
/* Write remaining records */
if lineout(DCD.List, OldList.M_Ix)<>0; then call DCD_Exit(7,'DCD.List')
End /* Do */
call stream DCD.List,'C','CLOSE' /* close file */
say "done."DCD.ColorReset
if DCD.CmdLin='' then call DCD_Exit 0
return
/* ===========================================================================
Valid_Drive: logical function to test valid drive
Usage: result=Valid_Drive(drive:)
Input: drive: drive letter followed by colon
Output: result=0 (invalid drive); result=1 (valid drive)
=========================================================================== */
Valid_Drive: procedure expose DCD.
parse upper arg Drive
Drive=filespec('D',Drive)
return verify(Drive,DCD.DriveMap)=0
/* ===========================================================================
DCD_Color: set colors for output
Usage: call DCD_Color <OnOff>
Input: Onoff character string, if ON set color, otherwise no color
Output: DCD.ColorNormal escape sequence to set color for normal text
DCD.ColorInput idem, for user input text
DCD.ColorBold idem, for bold text
DCD.ColorPrompt idem, for prompts
DCD.ColorError idem, for error messages
DCD.ColorReset escape sequence to reset text attributes
NOTE: requires ANSI ON
=========================================================================== */
DCD_Color: procedure expose DCD.
parse upper arg OnOff
if OnOff\='ON' then do
DCD.ColorNormal = ''
DCD.ColorInput = ''
DCD.ColorBold = ''
DCD.ColorPrompt = ''
DCD.ColorError = ''
DCD.ColorReset = ''
end /* Do */
else do
/* FG_Color: foreground color (according to ISO 6429 standard)
BG_Color: background color (according to ISO 6429 standard)
At_Attr: text attribute
*/
FG_Black ='30' ; BG_Black ='40' ; At_Off ='0'
FG_Red ='31' ; BG_Red ='41' ; At_Bold ='1'
FG_Green ='32' ; BG_Green ='42' ; At_Under ='4'
FG_Yellow ='33' ; BG_Yellow ='43' ; At_Blink ='5'
FG_Blue ='34' ; BG_Blue ='44' ; At_Reverse='7'
FG_Magenta='35' ; BG_Magenta='45' ; At_Conceal='8'
FG_Cyan ='36' ; BG_Cyan ='46'
FG_White ='37' ; BG_White ='47'
Esc=D2C(27) /* escape character */
DCD.ColorNormal = Esc'['At_Off';'FG_White';'BG_Blue'm'
DCD.ColorInput = Esc'['At_Bold';'FG_Yellow';'BG_Blue'm'
DCD.ColorBold = Esc'['At_Bold';'FG_White';'BG_Blue'm'
DCD.ColorPrompt = Esc'['At_Bold';'FG_Green';'BG_Blue'm'
DCD.ColorError = Esc'['At_Bold';'At_Blink';'FG_Yellow';'BG_Red'm'
DCD.ColorReset = Esc'['At_Off'm'
end /* Do */
return
/* ===========================================================================
DCD_Help: procedure to list help and then exit
Usage: call DCD_Help MODE
Input: MODE='' short help; MODE='VERBOSE' long help
=========================================================================== */
DCD_Help: procedure expose DCD.
parse arg VERBOSE
B=DCD.ColorBold /* abbraviate colors */
N=DCD.ColorNormal
say N
say "DCD disk change directory usage:"
say B"DCD [-?|-help] [-scan|-rescan <drives>] [-global|-full|-next]",
"[-opt] -<n>|<dir>"
if VERBOSE=''; then Do
say N"Type DCD -help for more help.",
"Read DCD.DOC for all options."; call DCD_Exit 0
End
say N
say "Change directory to <dir>, in which `<dir>' is part of a directory name"
say "(* and ? allowed) or <n> times up the tree.",
"Options start with `-' or `/'."
say "Startup options may be configured by setting the environment variable",
B||DCD.Src.Name||N"."
say N
say B"-?"N"|"||B"-H"N"elp|"||B"-V"N"ersion short help | long help |",
"display version number."
say B"-G"N"lobal|"||B"-L"N"ocal match directory on all | local drive(s)."
say B"-F"N"ullmatch require full match of directory name."
say B"-P"N"artialmatch partial match of directory name suffices."
say B"-N"N"ext do not query, jump to next match."
say B"-PU"N"shdir|"||B"-PO"N"pdir remember current dir |",
"jump back to pushed dir."
say B"-UP"N"percase|"||B"-LOW"N"ercase no case sensitivity (<dir> uppercase) |",
"case sensitivity."
say B"-\, -/, --"N" convert / to \, \ to /, or no conversion."
say B"-LI"N"st <file> use alternate directory list from <file>."
say B"-S"N"can <drives> scan drive(s); e.g., <drives>=cdE:fg."
say B"-RE"N"scan <drives> rescan drives, retain previous scan data."
say B"-E"N"xpression <dir> search for <dir>, useful if <dir> begins with -."
say B"-NOGREP"N" do not use grep for wildcard matching."
say B"-REGEX"N" force grep with <dir> as regular expression."
say B"-GREPO"N"pt <opt> pass <opt> to grep command."
say B"-COLOR"N" attempt to color your world..."
call DCD_Exit 0
return
/* ===========================================================================
DCD_Warn: procedure to give a warning message
Usage: call DCD_Warn Errcode Txt
Input: Warning code (0=no warning)
Txt text used in some of the warning messages
Output: None
=========================================================================== */
DCD_Warn: procedure expose DCD.
parse arg Wrn Txt
if Wrn <> 0; then do
if Txt='0D'x|Txt='08'x; then Txt=''
select
when Wrn=1; then Txt="No wildcard support for -global ("Txt")."
when Wrn=2; then Txt="No wildcard support for -fullmatch ("Txt")."
when Wrn=3; then Txt="Case sensitivity disabled ("Txt")."
otherwise; Txt="Something invoked warning "Wrn", but why?"
end
say DCD.ColorError"DCD Warning: "Txt DCD.ColorNormal
end
return
/* ===========================================================================
DCD_Exit: procedure to exit with error message
Usage: call DCD_Exit Errcode Txt
Input: Errcode error code to set (0=no error)
Txt text used in some of the error messages
Output: Errcode
=========================================================================== */
DCD_Exit: procedure expose DCD.
parse arg Err Txt
if Err <> 0; then do
if Txt='0D'x|Txt='08'x; then Txt=''
select
when Err=1; then Txt="Missing input. Try DCD -?"
when Err=2; then Txt="Unrecognized option ("Txt")."
when Err=3; then Txt="Missing file ("Txt"). Scan disks."
when Err=4; then Txt="Invalid drive ("Txt")."
when Err=5; then Txt="SysFileTree error scanning "Txt"."
when Err=6; then Txt="SysFileDelete error for "Txt"."
when Err=7; then Txt="Could not write to file "Txt"."
when Err=8; then Txt="Invalid directory ("Txt"). Scan disks."
when Err=9; then Txt="Invalid directory construct ("Txt")."
when Err=10; then Txt="SysFileSearch error ("Txt")."
when Err=11; then Txt="No match ("Txt"). Retype or scan disks."
when Err=12; then Txt="No full match ("Txt"). Retype or scan disks."
when Err=13; then Txt="Invalid selection ("Txt")."
when Err=14; then Txt="Invalid separator ("Txt")."
when Err=15; then Txt="No input. I quit."
when Err=16; then Txt="Grep required but not found. Use -nogrep."
when Err=17; then Txt="-regex and -nogrep contradictory."
when Err=18; then Txt=DCD.Src.Name"_Push environment variable not set."
when Err=99; then Txt="Sorry, function not implemented."
otherwise; Txt="Something invoked error "Err", but why?"
end
call charout , DCD.ColorError"DCD Error: "Txt
end
if DCD.CmdLin<>''; then do;
say
call lineout , "DCD Error: Command line ignored ("DCD.CmdLin")."
end
call charout , DCD.ColorReset
exit Err
return
/* ===========================================================================
DCD_Halt: display a random message on ctl_break (called by signal on halt)
=========================================================================== */
DCD_Halt:
Msg.0=5
Msg.1="Ctl_break is wonderful!"
Msg.2="Ctl_Break for the impatient!"
Msg.3="Ouch!"
Msg.4="Your wish is my command: I quit."
Msg.5="Bye bye!"
N=random(1,Msg.0)
say DCD.ColorError||Msg.N||DCD.ColorReset
/* ============================ end of DCD.CMD ============================ */